package channel

import (
	"context"
	"gitee.com/lipore/go-nio/pkg/frame"
	"sync"
)

type (
	Handler interface {
	}

	Context interface {
		reset(c Channel, handlers []Handler)
		Disconnect()
		Emit(msg frame.Frame)
		Next() error
		Set(string, any)
		Get(string) (any, bool)
		ChannelId() int64
		Channel() Channel
	}
)

type commonContext struct {
	ctx      context.Context
	channel  Channel
	index    int8
	Keys     map[string]any
	mu       sync.RWMutex
	handlers []Handler
}

func (c *commonContext) ChannelId() int64 {
	return c.channel.ID()
}

func (c *commonContext) Channel() Channel {
	return c.channel
}

// Disconnect will close a channel and its transport. After that the epoll or kqueue will send closed event to reactor.
// After that reactor will remove the channel from channels list.
func (c *commonContext) Disconnect() {
	_ = c.channel.Close()
}

func (c *commonContext) Emit(msg frame.Frame) {
	c.channel.Write(msg)
}

func (c *commonContext) reset(ch Channel, handlers []Handler) {
	c.index = -1
	c.Keys = nil
	c.channel = nil
	c.handlers = handlers
	c.channel = ch
}

func (c *commonContext) Set(key string, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.Keys == nil {
		c.Keys = make(map[string]any)
	}
	c.Keys[key] = value
}

func (c *commonContext) Get(key string) (value any, exist bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	value, exist = c.Keys[key]
	return
}
